#include "Triangle.h"

Triangle::Triangle() :
	normal(.0, .0, .0)
{
	vertices[0] = vertices[1] = vertices[2] = 0;
}

Triangle::Triangle(const Vertex* p[3], const Material* m) :
	normal(.0, .0, .0), material(m)
{
	vertices[0] = p[0];
	vertices[1] = p[1];
	vertices[2] = p[2];
}

Triangle::~Triangle()
{
}

Vector Triangle::getNormal(const SPoint& hit) const
{
	return ~(vertices[0]->getNormal() * (1. - triAccel.u - triAccel.v) + vertices[1]->getNormal() * triAccel.u + vertices[2]->getNormal() * triAccel.v);
//	return normal;
}


void Triangle::precalculate(const SPoint& viewPoint)
{
	// calculate triAccel-struture
	Vector c = vertices[1]->getPoint() - vertices[0]->getPoint();
	Vector b = vertices[2]->getPoint() - vertices[0]->getPoint();
	
	// calculate normal-vector
	normal = ~Vector::crossProduct(c, b);
	
	//projection-dimension
	triAccel.k = (fabs(normal.x) > fabs(normal.y)) ? ((fabs(normal.x) > fabs(normal.z)) ? X : Z) : ((fabs(normal.y) > fabs(normal.z)) ? Y : Z);
	
	Vector nn = normal / normal.get(triAccel.k);
	
	// n_u, n_v and n_d
	const int uAxis = modulo3[triAccel.k + 1];
	const int vAxis = modulo3[triAccel.k + 2];
	triAccel.n_u = nn.get(uAxis);
	triAccel.n_v = nn.get(vAxis);
	triAccel.n_d = Vector::dotProduct(Vector(vertices[0]->getPoint().get(X), vertices[0]->getPoint().get(Y), vertices[0]->getPoint().get(Z)), nn);

	// first line equation
	float reci = 1. / (b.get(uAxis) * c.get(vAxis) - b.get(vAxis) * c.get(uAxis));
	triAccel.b_nu = b.get(uAxis) * reci;
	triAccel.b_nv = -b.get(vAxis) * reci;
	triAccel.b_d = (b.get(vAxis) * vertices[0]->getPoint().get(uAxis) - b.get(uAxis) * vertices[0]->getPoint().get(vAxis)) * reci;
	// second line equation
	triAccel.c_nu = c.get(uAxis) * -reci;
	triAccel.c_nv = c.get(vAxis) * reci;
	triAccel.c_d = (c.get(vAxis) * vertices[0]->getPoint().get(uAxis) - c.get(uAxis) * vertices[0]->getPoint().get(vAxis)) * -reci;
}
